package com.yami.shop.mp.component;

import com.yami.shop.common.annotation.RedisLock;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.mp.config.bean.WxCp;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.locks.Lock;

/**
 * 基于Redis的微信配置provider.
 *
 * 已加入分布式锁的实现
 *
 * @author LGH
 */
@Component
public class WxCpInRedisConfig extends WxCpDefaultConfigImpl {

    private static final String ACCESS_TOKEN_KEY = "wxCp:access_token:";

    private static final String JSAPI_TICKET_KEY = "wxCp:jsapi_ticket:";

    private static final String CARD_API_TICKET_KEY = "wxCp:card_api_ticket:";

    private static final String WX_MA_ACCESS_TOKEN_LOCK = "wxCp:access_token_lock:";

    private static final String WX_MA_JSAPI_TICKET_LOCK = "wxCp:jsapi_ticket_lock:";

    private static final String WX_MA_CARD_API_TICKET_LOCK = "wxCp:card_api_ticket_lock:";

    private String accessTokenKey;

    private String jsapiTicketKey;

    private String cardApiTicketKey;

    @Autowired
    private RedissonClient redissonClient;

    public WxCpInRedisConfig(WxCp wxCp) {
        this.setCorpId(wxCp.getCorpId());
        this.setAgentId(wxCp.getAgentId());
        this.setCorpSecret(wxCp.getSecret());
        this.setToken(wxCp.getToken());
        this.setAesKey(wxCp.getAesKey());
    }

    /**
     * 每个公众号生成独有的存储key.
     */
    @Override
    public void setCorpId(String corpId) {
        super.setCorpId(corpId);
        this.accessTokenKey = ACCESS_TOKEN_KEY.concat(corpId);
        this.jsapiTicketKey = JSAPI_TICKET_KEY.concat(corpId);
        this.cardApiTicketKey = CARD_API_TICKET_KEY.concat(corpId);
    }

    @Override
    public String getAccessToken() {
        return RedisUtil.get(accessTokenKey);
    }

    @Override
    public Lock getAccessTokenLock(){
        return redissonClient.getLock(WX_MA_ACCESS_TOKEN_LOCK);
    }

    @Override
    public boolean isAccessTokenExpired() {
        return !RedisUtil.hasKey(accessTokenKey);
    }

    @Override
    public void expireAccessToken() {
        RedisUtil.del(accessTokenKey);
    }

    @Override
    @RedisLock(lockName = "updateCpAccessToken")
    public void updateAccessToken(WxAccessToken accessToken) {
        updateAccessToken(accessToken.getAccessToken(), accessToken.getExpiresIn());
    }


    @Override
    @RedisLock(lockName = "updateCpAccessToken")
    public void updateAccessToken(String accessToken, int expiresInSeconds) {
        RedisUtil.set(accessTokenKey, accessToken, expiresInSeconds - 200);
    }

    @Override
    public String getJsapiTicket() {
        return RedisUtil.get(jsapiTicketKey);
    }

    @Override
    public Lock getJsapiTicketLock() {
        return redissonClient.getLock(WX_MA_JSAPI_TICKET_LOCK);
    }

    @Override
    public boolean isJsapiTicketExpired() {
        return !RedisUtil.hasKey(jsapiTicketKey);
    }

    @Override
    public void expireJsapiTicket() {
        RedisUtil.del(jsapiTicketKey);
    }

    @Override
    @RedisLock(lockName = "updateCpJsapiTicket")
    public void updateJsapiTicket(String jsapiTicket, int expiresInSeconds) {
        RedisUtil.set(jsapiTicketKey, jsapiTicket, expiresInSeconds - 200);
    }
}
